using IQIGame.Onigao.Game;
using IQIGame.Onigao.Logic;
using System;

namespace IQIGame.Onigao.GamePlay
{
    public class CFSMState_Level_Logic_Monster_Alert : CFSMState<IQIGame.Onigao.Logic.LevelEntity, CFSMLevel_Logic_MonsterData>
    {
        private LevelHeroEntity _detectedEnemyEntity;
        public override void OnInit()
        {

        }

        public override void OnEnter(int prevStateId)
        {
            _detectedEnemyEntity = _detectedEnemyEntity ?? LgLevelEntityUtil.GetHeroInSight(entity);
            if (_detectedEnemyEntity == null)
            {
                LogicLog.LogError("刷新警戒值时却没有找到任何英雄？");
                return;
            }
            data.dirBeforeChase = entity.dir;
            SetAlertValueAndNotify(1, true);
        }

        public override void OnUpdate(float deltaTime)
        {
            if (_detectedEnemyEntity == null)
            {
                return;
            }
            float alertValue = data.alertValue;
            if (_detectedEnemyEntity.isUndetectable)
            {
                if (alertValue > 0)
                {
                    alertValue = 0;
                    SetAlertValueAndNotify(alertValue);
                }
                return;
            }
            int viewRange = entity.entityConfig.viewRange;
            float sqrDistance = CalcConfirmedHeroSqrDistance(_detectedEnemyEntity);
            //如果没有英雄靠近，则警戒值逐渐减少
            if (sqrDistance >= viewRange * viewRange)
            {
                alertValue -= ShareLevelConst.AlertReduceDelta * LgLevelConst.StateMachineUpdateInterval;
                alertValue = alertValue < 0 ? 0 : alertValue;
            }
            //否则根据英雄的距离按比例增长
            else
            {
                int minDetaPerSec = ShareLevelConst.AlertAddMinDelta;
                int maxDeltaPerSec = ShareLevelConst.AlertAddMaxDelta;
                float distance = (float)Math.Sqrt(sqrDistance);
                float minDelta = minDetaPerSec * LgLevelConst.StateMachineUpdateInterval;
                float maxDelta = maxDeltaPerSec * LgLevelConst.StateMachineUpdateInterval;
                alertValue += ShareLevelMathUtil.PlummetCurve(distance, viewRange, minDelta, maxDelta);
                alertValue = alertValue > 100 ? 100 : alertValue; //最大是100%
            }
            //警戒值大于0时始终面朝玩家
            if (alertValue > 0)
            {
                var dir = _detectedEnemyEntity.position - entity.position;
                dir.y = 0;
                entity.dirUnnormalized = dir;
            }
            //仅alertValue为0或100时通知，或参数forceNotify为true时通知
            SetAlertValueAndNotify(alertValue);
        }

        private float CalcConfirmedHeroSqrDistance(LevelHeroEntity target)
        {
            float sqrDistance = int.MaxValue;
            if (target == null)
            {
                return sqrDistance;
            }
            if (target.navigator.isPhysical)
            {
                return sqrDistance;
            }
            sqrDistance = (target.position - entity.position).sqrMagnitude;
            return sqrDistance;
        }

        /// <summary>
        /// 通知客户端警戒值变化
        /// </summary>
        /// <param name="value"></param>
        /// <param name="forceNotify"></param>
        private void SetAlertValueAndNotify(float value, bool forceNotify = false)
        {
            data.alertValue = value;
            //仅alertValue为0或100时通知，或参数forceNotify为true时通知
            if (data.alertValue == 0 || data.alertValue == 100 || forceNotify)
            {
                entity.ChangeAlertEnemy(_detectedEnemyEntity, data.alertValue);
            }
        }

        public override void OnExit()
        {
            //在警戒状态被强制退出，需要同步一次警戒值给客户端，清除警戒表现
            if (data.alertValue > 0 && data.alertValue < 100)
            {
                SetAlertValueAndNotify(0);
            }
            if (data.alertValue >= 100)
            {
                data.lockingEntity = _detectedEnemyEntity;
            }
        }

        public override void OnReset()
        {
            _detectedEnemyEntity = null;
            base.OnReset();
        }
    }
}
